package com.jiandan.plugin.module


import com.jiandan.plugin.PluginExtension

import groovy.io.FileType

import org.gradle.api.GradleException

class Firm {

    PluginExtension config
    File jar
    File firmJarParentPath
    Firm(PluginExtension config) {
        this.config = config
        firmJarParentPath = new File(config.firmJarPath)
        jar = new File(firmJarParentPath, "jiagu/jiagu.jar")
    }

    def firmApkAndUpload() {
        makeFirmDir(config.firmEnable)
        if (config.moveReleaseApk && config.getApkIsBuild()) {
            movieApk(config.apkFilePath)
        }
        if (config.firmEnable) {
            firm360()
        }
    }

    private makeFirmDir(boolean deleteOldFile) {
        File firmResultFile = new File(config.outPath + "/" + config.firmResultDirName)
        if (firmResultFile.exists()) {
            if (deleteOldFile) {
                firmResultFile.deleteDir()
                firmResultFile.mkdirs()
            }
        } else {
            firmResultFile.mkdirs()
        }
    }

    private movieApk(String path) {
        def apkFileDes = new File(config.outPath + "/" + config.firmResultDirName, config.appName + "_" + config.apkVersionName + "_" + config.apkVersionCode + ".apk")
        File apkFile = new File(path)
        if (apkFileDes.exists()) {
            apkFileDes.delete()
        }
        boolean result = apkFile.renameTo(apkFileDes)
        println("move apk from $path")
        println("move apk to $apkFileDes.absolutePath")
        println("move apk result $result")
        config.apkFilePath = result ? apkFileDes.absolutePath : path
    }


    /**
     * 360加固 流程
     * 1、登录
     * 2、添加签名
     * 3、添加渠道
     * 4、清除配置
     * 5、加固
     */
    private firm360() {
        login()
        addSignInfo()
        addChannelInfo()
        clearFirmService()
        startFirm()
    }
    /**
     * 360加固 登录
     */
    private login() {
        if (!jar.exists()) {
            def os = System.getProperty("os.name").toLowerCase()
            if (os.contains("linux")) {
                // 360加固linux 的文件夹里面的摆放和其他的不一样，需要处理
                firmJarParentPath.eachFile { child ->
                    "mv ${new File(child, "jiagu").absolutePath} $child.parent".execute()
                }
            }
        }
        println("360加固-> 登录")
        String loginShell = "java -jar $jar.absolutePath -login $config.firmAccountName $config.firmAccountPwd"
        def out = new StringBuilder(), err = new StringBuilder()
        executeShell(loginShell, out, err, 10000, true)
        if (out.length() <= 0 || (!out.contains("login success") && !out.contains("loading success"))) {
            def errorText = err.toString()
            if (errorText.length() == 0) {
                errorText = out.toString()
            }
            errorText = errorText.replaceAll("\n", "")
            println("加固 登录失败 " + errorText)
            throw new GradleException("加固 登录失败 " + errorText)
        }
    }
    /**
     * 360加固 添加签名信息
     */
    private def addSignInfo() {
        println("360加固-> 添加签名信息")
        if (!new File(config.storeFilePath).exists()) {
            throw new GradleException("签名文件不存在: $config.storeFilePath")
        }
        def firmShell = "java -jar $jar.absolutePath -importsign $config.storeFilePath $config.storePassword $config.keyAlias $config.keyPassword"
        def out = new StringBuilder(), err = new StringBuilder()
        executeShell(firmShell, out, err, 5000, false)
        if (err.length() > 0) {
            throw new GradleException("加固 添加签名失败 " + replaceAll("\n", ""))
        }
    }

    /**
     * 360加固 添加渠道信息
     */
    private def addChannelInfo() {
        println("360加固-> 添加渠道信息")
        def firmShell = "java -jar $jar.absolutePath -importmulpkg $config.channelFilePath"
        if (config.channelFilePath != null) {
            if (!new File(config.channelFilePath).exists()) {
                throw new GradleException("渠道配置文件不存在: $config.channelFilePath")
            }
        } else {
            firmShell = "java -jar $jar.absolutePath -deletemulpkg"
        }
        def out = new StringBuilder(), err = new StringBuilder()
        executeShell(firmShell, out, err, 5000, false)
        if (err.length() > 0) {
            throw new GradleException("加固 添加渠道信息失败 " + replaceAll("\n", ""))
        }
        firmShell = "java -jar $jar.absolutePath -showmulpkg"
        out = new StringBuilder()
        err = new StringBuilder()
        executeShell(firmShell, out, err, 5000, false)
        if (err.length() > 0) {
            throw new GradleException("加固 添加渠道信息失败 " + replaceAll("\n", ""))
        }
    }

    /**
     * 360加固 配置打包增强配置
     */
    private def clearFirmService() {
        println("360加固-> 配置打包增强配置")
        def firmShell = "java -jar $jar.absolutePath -config $config.firm360Config"
        def out = new StringBuilder(), err = new StringBuilder()
        executeShell(firmShell, out, err, 5000, false)
        if (err.length() > 0) {
            throw new GradleException("加固 打包增强配置失败 " + replaceAll("\n", ""))
        }
    }

    /**
     * 360加固 加固
     */
    private def startFirm() {
        println("360加固-> 加固开始")
        def firmReleaseDir = new File(config.outPath + "/" + config.firmResultDirName + "/" + config.apkVersionName)
        firmReleaseDir.mkdirs()
        def firmShell = "java -jar $jar.absolutePath -jiagu $config.apkFilePath $firmReleaseDir.absolutePath -autosign"
        if (config.channelFilePath != null) {
            firmShell = firmShell + " -automulpkg"
        }
        def out = new StringBuilder(), err = new StringBuilder()
        executeShell(firmShell, out, err, 1000 * 60 * 10, false)
        if (err.length() > 0) {
            println(err.toString())
            if (!err.contains("error=13, Permission denied")) {
                println("error 360加固 失败" + err.toString().replaceAll("\n", ""))
                return
            }
        }
        if (out.length() <= 0 || !(out.contains("已加固") || out.contains("任务完成"))) {
            println(out.toString())
            println("error 360加固 失败 详细信息如上")
            return
        }
        println("success 360加固 完成 $firmReleaseDir")
        def verName = config.apkVersionName.replaceAll("\\.", "")
        verName = "_" + verName
        String buildChannelApk = null
        String lastUploadApk = null
        firmReleaseDir.eachFileMatch(FileType.FILES, ~/.*\.apk/) {
            //重命名文
            if (it.name.endsWith("_sign.apk")) {
                def newName = it.name.replaceAll(verName, "").replaceAll("_sign", "")
                def newFile = new File(it.parent, newName)
                it.renameTo(newFile)
                lastUploadApk = newFile.absolutePath
                if (buildChannelApk == null && config.buildChannel != null) {
                    if (newName.endsWith(config.buildChannel + ".apk")) {
                        buildChannelApk = newFile.absolutePath
                    }
                }
            }
        }
        println("success 360加固 文件重命名成功 $firmReleaseDir")
        if (buildChannelApk != null) {
            config.apkFilePath = buildChannelApk
            return
        }
        if (config.buildChannel == null) {
            config.apkFilePath = lastUploadApk
            println("warn 未设置 buildChannel")
            return
        }
        config.apkFilePath = lastUploadApk
        println("warn 未找到设置的 buildChannel : " + config.buildChannel)
    }
    /**
     * 执行shell 脚本
     */
    private def executeShell(String shellStr,
                     StringBuilder out,
                     StringBuilder err,
                     int millis,
                     boolean showLogo) {
        println("shell cmd : $shellStr")
        def process = shellStr.execute()
        //此处会导致out 没有东西
        String charType = config.getOsName() == "win" ? "GBK" : "UTF-8"
        BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream(), charType))
        String inline
        while ((inline = br.readLine()) != null) {
            if (showLogo || !inline.startsWith("#")) {
                if (inline != "") {
                    println(inline)
                    if (!inline.startsWith("#")) {
                        if (inline != "") {
                            out.append(inline).append("\n")
                        }
                    }
                }
            }
        }
        process.consumeProcessOutput(out, err)
        process.waitForOrKill(millis)
        // br.close() 会报错
    }

}
